package cn.com.demo.cms;

import cn.com.demo.cert.X509CertificateExample;
import cn.com.demo.keystore.JKSKeystoreExample;
import org.bouncycastle.cms.CMSProcessable;
import org.bouncycastle.cms.CMSProcessableByteArray;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.CMSSignedDataGenerator;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Base64;

import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.CertStore;
import java.security.cert.Certificate;
import java.security.cert.CollectionCertStoreParameters;
import java.security.cert.X509Certificate;
import java.util.Arrays;

public class SignedDataExample extends SignedDataProcessor {

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    /**
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {

        KeyStore store = JKSKeystoreExample.createKeyStore();
        PrivateKey priKey = (PrivateKey) store.getKey(X509CertificateExample.END_ALIAS, JKSKeystoreExample.password);
        Certificate[] chain = store.getCertificateChain(X509CertificateExample.END_ALIAS);

        CertStore certStore = CertStore.getInstance(
                "Collection", new CollectionCertStoreParameters(Arrays.asList(chain)), "BC");

        X509Certificate cert = (X509Certificate) chain[0];

        //set up the generator
        CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
        gen.addSigner(priKey, cert, CMSSignedDataGenerator.DIGEST_SHA256);
        gen.addCertificatesAndCRLs(certStore);

        //create the signed-data object
        CMSProcessable data = new CMSProcessableByteArray("Hello World!".getBytes());

        CMSSignedData signed = gen.generate(data, "BC");
        System.out.println(new String(Base64.encode(signed.getEncoded())));
        //re-create
        signed = new CMSSignedData(data, signed.getEncoded());

        //verification setup
        X509Certificate rootCert = (X509Certificate) store.getCertificate(X509CertificateExample.ROOT_ALIAS);

        if (isValid(signed, rootCert)) {
            System.out.println("verification successfully.");
        } else {
            System.out.println("verification failed.");
        }
    }

}
